package com.ruoyi.system.service;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.core.domain.Domain;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.PageResult;
import com.ruoyi.common.core.page.TableSupport;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.system.domain.CashHistory;
import com.ruoyi.system.mapper.BaseDao;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Slf4j
public class BaseServiceImpl<M extends BaseDao<T>, T extends Domain> extends ServiceImpl<M, T> implements BaseService<T> {
    @Override
    public T addDomain(T domain) {
        boolean is_save = this.save(domain);
        return is_save ? domain : null;
    }

    @Override
    public boolean addDomainBatch(List<T> list) {
        return this.saveBatch(list);
    }


    @Override
    public boolean delById(Long id) {
        int i = this.baseMapper.deleteById(id);
        return i == 1 ? true : false;
    }

    @Override
    public int delDomain(T domain) {
        QueryWrapper<T> queryWrapper = new QueryWrapper(domain);
        return this.baseMapper.delete(queryWrapper);

    }

    public static void main(String[] args) {
        CashHistory cashHistory = new CashHistory();
        cashHistory.setOrderNo("1213");
        JSONObject jsonObject = JSONUtil.parseObj(cashHistory);
        System.out.println(jsonObject.toString());

    }
    private String getCounm(T domain){
        CashHistory cashHistory = new CashHistory();

        JSONObject jsonObject = JSONUtil.parseObj(cashHistory);
        System.out.println(jsonObject.toString());
        return  null;

    }
    public static boolean hasIdField(Object obj) {
        // 获取对象的Class对象
        Class<?> clazz = obj.getClass();

        // 获取所有的字段
        Field[] fields = clazz.getDeclaredFields();

        // 遍历字段，判断是否有名为id的字段
        for (Field field : fields) {
            if (field.getName().equals("id")) {
                return true;
            }
        }

        return false;
    }

    @Override
    public void delByIds(List<Long> ids) {
        this.baseMapper.deleteBatchIds(ids);
    }

    @Override
    public T updateDomain(T domain) {
        int i = this.baseMapper.updateById(domain);
        return i > 0 ? domain : null;
    }
    @Override
    public T updateDomainNullId(T domain, String col, Object obj) {
        UpdateWrapper updateWrapper = new UpdateWrapper(domain);
        updateWrapper.set(col, obj);
        this.update(updateWrapper);
        int i = this.baseMapper.updateById(domain);
        return i > 0 ? domain : null;
    }

    @Override
    public boolean saveOrUpdateBatch(List<T> list) {
        return super.saveOrUpdateBatch(list);
    }

    @Override
    public boolean updateBatchById(List<T> list) {
        return super.updateBatchById(list);
    }

    @Override
    public T getDomain(T t) {
        QueryWrapper<T> query = new QueryWrapper(t);
        return this.baseMapper.selectOne(query);
    }

    public T check(Long id) {

        T t = this.getById(id);
        if (t == null) {
            log.info("数据不存在:{}", id);
            throw new RuntimeException("数据不存在");
        }
        return t;
    }

    @Override
    public T getById(Long id) {
        return this.baseMapper.selectById(id);
    }

    @Override
    public List<T> findByIds(List<Long> ids) {
        return this.baseMapper.selectBatchIds(ids);
    }

    @Override
    public List<T> findList(T t, PageDomain pageDomain) {
        String sortName;
        // 判断对象是否有id属性
        boolean hasId = hasIdField(t);
        if (hasId) {
            sortName = "id";
        } else {
            sortName = "create_time";
        }

        if (pageDomain.getPageNo() != null) {
            pageDomain.setPageNum(pageDomain.getPageNo());
        }
        PageUtils.startPage(pageDomain);
        QueryWrapper<T> query = new QueryWrapper(t);
        query.between(StrUtil.isNotBlank(pageDomain.getBeginTime()), "create_time", pageDomain.getBeginTime(), pageDomain.getEndTime());
        IPage<T> page = new Page<T>();
        page.setCurrent(pageDomain.getPageNum());
        page.setSize(pageDomain.getPageSize());
        setQuery(query);
        query.orderByDesc(sortName);
        List<T> records = this.baseMapper.selectPage(page, query).getRecords();
        return records;
    }

    @Override
    public List<T> findList(T t) {
        String sortName;
        // 判断对象是否有id属性
        boolean hasId = hasIdField(t);
        if (hasId) {
            sortName = "id";
        } else {
            sortName = "create_time";
        }
        QueryWrapper<T> query = new QueryWrapper(t);
        PageDomain pageDomain = TableSupport.buildPageRequest();
        Map<String, Object> params = t.getParams();
        if (params != null) {
            query.between(!ObjectUtils.isEmpty(params.get("beginTime")), "create_time", params.get("beginTime") + " 00:00:00", params.get("endTime") + " 23:59:59");
        }
        IPage<T> page = new Page<T>();
        page.setCurrent(pageDomain.getPageNum());
        page.setSize(pageDomain.getPageSize());
        String orderByColumn = pageDomain.getOrderByColumn();
        String isAsc = pageDomain.getIsAsc();
        setQuery(query);
        if (StrUtil.isBlank(orderByColumn)) {
            orderByColumn = sortName;
        }
        if (StrUtil.isBlank(isAsc)) {
            isAsc = "desc";
        }
        if ("desc".equals(isAsc)) {
            query.orderByDesc(StrUtil.toUnderlineCase(orderByColumn));
        } else {
            query.orderByAsc(StrUtil.toUnderlineCase(orderByColumn));
        }
        PageHelper.startPage(pageDomain.getPageNum(), pageDomain.getPageSize());
        List<T> records = this.baseMapper.selectList(query);
        return records;
    }

    public List<T> list(T t) {
        String sortName;
        // 判断对象是否有id属性
        boolean hasId = hasIdField(t);
        if (hasId) {
            sortName = "id";
        } else {
            sortName = "create_time";
        }
        QueryWrapper<T> query = new QueryWrapper(t);
        Map<String, Object> params = t.getParams();
        if (params != null) {
            query.between(!ObjectUtils.isEmpty(params.get("beginTime")), "create_time", params.get("beginTime") + " 00:00:00", params.get("endTime") + " 23:59:59");
        }
        setQuery(query);
        query.orderByDesc(sortName);
        List<T> records = this.baseMapper.selectList(query);
        return records;
    }


    protected void setQuery(QueryWrapper<T> query) {

    }


    @Override
    public List<T> findListLike(T t) {
        QueryWrapper<T> query = getQueryWrapper(t);
        PageDomain pageDomain =new PageDomain();
        Map<String, Object> params = t.getParams();
        if (params != null && params.size() > 0) {
            query.between(!ObjectUtils.isEmpty(params.get("beginTime")), "create_time", params.get("beginTime") + " 00:00:00", params.get("endTime") + " 23:59:59");
        }
        IPage<T> page = new Page<T>();
        page.setCurrent(pageDomain.getPageNum());
        page.setSize(pageDomain.getPageSize());
        List<T> records = this.baseMapper.selectPage(page, query).getRecords();
        return records;
    }

    @Override
    public PageResult<T> findPage(T t, PageDomain pageDto) {
        QueryWrapper<T> query = new QueryWrapper(t);
        query.between(StrUtil.isNotBlank(pageDto.getBeginTime()), "create_time", pageDto.getBeginTime() + " 00:00:00", pageDto.getEndTime() + " 23:59:59");
        IPage<T> page = new Page<T>();
        page.setCurrent(pageDto.getPageNum());
        page.setSize(pageDto.getPageSize());
        if (StrUtil.equals(pageDto.getIsAsc(), "asc")) {
            query.orderByAsc(StrUtil.toUnderlineCase(pageDto.getOrderByColumn()));
        } else {
            query.orderByDesc(StrUtil.toUnderlineCase(pageDto.getOrderByColumn()));
        }
        List<T> records = this.baseMapper.selectPage(page, query).getRecords();

        return this.getResult(records);
    }

    @Override
    public BigDecimal sum(String clo, T t, Date startTime, Date endTime) {
        QueryWrapper<T> query = new QueryWrapper(t);
        query.gt(startTime != null, "create_time", startTime);
        query.le(startTime != null, "create_time", endTime);
        query.select("sum(" + StrUtil.toUnderlineCase(clo) + ") as " + clo);
        T domain = this.baseMapper.selectOne(query);
        JSONObject jsonObject = JSONUtil.parseObj(domain);
        BigDecimal bigDecimal = jsonObject.getBigDecimal(clo);
        return bigDecimal == null ? BigDecimal.ZERO : bigDecimal;
    }
    @Override
    public BigDecimal sum(String clo, T t, Date startTime, Date endTime, String cloTime) {
        QueryWrapper<T> query = new QueryWrapper(t);
        query.gt(startTime != null, StrUtil.toUnderlineCase(cloTime), startTime);
        query.le(startTime != null, StrUtil.toUnderlineCase(cloTime), endTime);
        query.select("sum(" + StrUtil.toUnderlineCase(clo) + ") as " + clo);
        T domain = this.baseMapper.selectOne(query);
        JSONObject jsonObject = JSONUtil.parseObj(domain);
        BigDecimal bigDecimal = jsonObject.getBigDecimal(clo);
        return bigDecimal == null ? BigDecimal.ZERO : bigDecimal;
    }

    protected PageResult<T> getResult(List<T> records) {
        PageInfo pageInfo = new PageInfo(records);
        PageResult<T> result = new PageResult();
        result.setPageNum(pageInfo.getPageNum());
        result.setPageSize(pageInfo.getPageSize());
        result.setList(records);
        result.setTotal(pageInfo.getTotal());
        return result;
    }

    @Override
    public int countByDomain(T domain) {
        QueryWrapper<T> wrapper = new QueryWrapper(domain);
        int count = this.count(wrapper);
        return count;
    }
    @Override
    public int countByDomain(T domain, Date startTime, Date endTime, String cloTime) {
        QueryWrapper<T> wrapper = new QueryWrapper(domain);
        wrapper.between(startTime != null, StrUtil.toUnderlineCase(cloTime), startTime, endTime);
        int count = this.count(wrapper);
        return count;
    }

    @Override
    public int countByDomain(T domain, Date startTime, Date endTime) {
        QueryWrapper<T> wrapper = new QueryWrapper(domain);
        wrapper.between(startTime != null, "create_time", startTime, endTime);
        int count = this.count(wrapper);
        return count;
    }


    protected QueryWrapper<T> getQueryWrapper(T t) {
        Field[] fields = t.getClass().getDeclaredFields();
        QueryWrapper<T> queryWrapper = new QueryWrapper<T>();
        this.setWrapper(t, queryWrapper, fields);
        fields = t.getClass().getSuperclass().getDeclaredFields();
        this.setWrapper(t, queryWrapper, fields);

        return queryWrapper;
    }

    private void setWrapper(T t, QueryWrapper<T> wrapper, Field[] fields) {
        try {
            int length = fields.length;
            for (int i = 0; i < length; i++) {
                Field field = fields[i];
                String name = field.getName();
                field.setAccessible(true);
                String obj = (String) field.get(t);
                //如果有值就进行like操作
                if (!ObjectUtils.isEmpty(obj)) {
                    obj = obj.trim();
                    TableField annotation = (TableField) field.getAnnotation(TableField.class);
                    String column = "";
                    if (annotation != null) {
                        //如果有注解  就使用注解上面的映射字段
                        column = annotation.value();
                    } else {
                        //否则使用驼峰命名格式
                        column = StrUtil.toUnderlineCase(name);
                    }
                    if (StrUtil.endWith(name, "id") || StrUtil.endWith(name, "Id")) {
                        wrapper.eq(column, obj);
                    } else {
                        wrapper.like(column, obj);
                    }
                }
            }
        } catch (Exception e) {
            log.info(e.getMessage());
        }

    }

}

